Linux 容器幕后探秘

通过使用 LXC 来理解容器的工作原理,成为更出色的容器故障排除员。
305 位读者喜欢这篇文章。
Avoiding data disasters with Sanoid

Opensource.com

没有 Docker,可以有 Linux 容器吗?没有 OpenShift,可以有 Linux 容器吗?没有 Kubernetes,可以有 Linux 容器吗?

答案是肯定的。早在 Docker 让容器成为家喻户晓的术语(如果您身处数据中心,情况确实如此)的数年前,LXC 项目就开发了运行一种虚拟操作系统的概念,它共享相同的内核,但包含在定义的进程组中。

Docker 构建于 LXC 之上,如今,有许多平台直接或间接地利用了 LXC 的工作成果。大多数这些平台都使创建和维护容器变得极其简单,对于大型部署而言,使用此类专用服务是有意义的。然而,并非每个人都在管理大型部署,或者能够访问大型服务来学习容器化。好消息是,您只需一台运行 Linux 的 PC 和本文,就可以创建、使用和学习容器。本文将通过研究 LXC,探讨其工作原理、工作原因以及在出现问题时如何进行故障排除,帮助您理解容器。

绕过简易性

如果您正在寻找 LXC 的快速入门指南,请参阅优秀的 Linux 容器 网站。

安装 LXC

如果尚未安装,您可以使用您的软件包管理器安装 LXC

在 Fedora 或类似系统上,输入

$ sudo dnf install lxc lxc-templates lxc-doc

在 Debian、Ubuntu 和类似系统上,输入

$ sudo apt install lxc

创建网络桥接

大多数容器都假定网络可用,而大多数容器工具都期望用户能够创建虚拟网络设备。容器所需的最基本单元是网络桥接,它或多或少是网络交换机的软件等效物。网络交换机有点像智能 Y 型适配器,用于拆分耳机插孔,以便两个人可以使用单独的耳机听到相同的内容,只不过网络交换机桥接的是网络数据,而不是音频信号。

您可以创建自己的软件网络桥接,以便您的主机和容器操作系统都可以通过单个网络设备(以太网端口或无线网卡)发送和接收不同的网络数据。这是一个重要的概念,一旦您从手动生成容器毕业,通常会被忽略,因为无论您的部署规模有多大,您都不太可能为运行的每个容器配备专用的物理网卡。理解容器与虚拟网络设备通信至关重要,这样您就知道在容器失去网络连接时从哪里开始进行故障排除。

要在您的机器上创建网络桥接,您必须具有相应的权限。对于本文,请使用 sudo 命令以 root 权限操作。(但是,LXC 文档提供了在不使用 sudo 的情况下授予用户执行此操作的权限的配置。)

$ sudo ip link add br0 type bridge

验证是否已创建虚拟网络接口

$ sudo ip addr show br0
7: br0: <BROADCAST,MULTICAST> mtu 1500 qdisc
   noop state DOWN group default qlen 1000
   link/ether 26:fa:21:5f:cf:99 brd ff:ff:ff:ff:ff:ff

由于 br0 被视为网络接口,因此它需要自己的 IP 地址。选择一个有效的本地 IP 地址,该地址不与网络上的任何现有 IP 地址冲突,并将它分配给 br0 设备

$ sudo ip addr add 192.168.168.168 dev br0

最后,确保 br0 正在运行

$ sudo ip link set br0 up

设置容器配置

LXC 容器的配置文件可以根据需要变得复杂,以定义容器在您的网络和主机系统中的位置,但对于此示例,配置很简单。在您喜欢的文本编辑器中创建一个文件,并定义容器的名称和网络所需的设置

lxc.utsname = opensourcedotcom
lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = br0
lxc.network.hwaddr = 4a:49:43:49:79:bd
lxc.network.ipv4 = 192.168.168.1/24
lxc.network.ipv6 = 2003:db8:1:0:214:1234:fe0b:3596

将此文件保存在您的主目录中,命名为 mycontainer.conf

lxc.utsname 是任意的。您可以随意命名您的容器;这是您在启动和停止容器时将使用的名称。

网络类型设置为 veth,这是一种虚拟以太网跳线。其理念是 veth 连接从容器连接到桥接设备,桥接设备由 lxc.network.link 属性定义,设置为 br0。容器的 IP 地址与桥接设备在同一网络中,但必须是唯一的,以避免冲突。

除了 veth 网络类型和 up 网络标志之外,配置文件中的所有值都是您自己发明的。属性列表可从 man lxc.container.conf 中获得。(如果您的系统上缺少该列表,请在您的软件包管理器中查找单独的 LXC 文档包。)在 /usr/share/doc/lxc/examples 中有几个示例配置文件,您稍后应该查看它们。

启动容器 shell

此时,您已经完成了可操作容器的三分之二:您拥有网络基础设施,并且您已经在虚拟 PC 中安装了虚拟网卡。现在您只需要安装操作系统。

然而,即使在这个阶段,您也可以通过在容器空间内启动 shell 来查看 LXC 的工作原理。

$ sudo lxc-execute --name basic \
--rcfile ~/mycontainer.conf /bin/bash \
--logfile mycontainer.log
#

在这个非常简陋的容器中,查看您的网络配置。它应该看起来既熟悉又独特。

# /usr/sbin/ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state [...]
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
[...]
22: eth0@if23: <BROADCAST,MULTICAST,UP,LOWER_UP> [...] qlen 1000
link/ether 4a:49:43:49:79:bd brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.168.168.167/24 brd 192.168.168.255 scope global eth0
   valid_lft forever preferred_lft forever
inet6 2003:db8:1:0:214:1234:fe0b:3596/64 scope global 
   valid_lft forever preferred_lft forever
[...]

您的容器知道其伪造的网络基础设施和熟悉而独特的内核。

# uname -av
Linux opensourcedotcom 4.18.13-100.fc27.x86_64 #1 SMP Wed Oct 10 18:34:01 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

使用 exit 命令退出容器

# exit

安装容器操作系统

构建完整的容器化环境比网络和配置步骤复杂得多,因此您可以从 LXC 借用容器模板。如果您没有任何模板,请在您的软件仓库中查找单独的 LXC 模板包。

默认的 LXC 模板位于 /usr/share/lxc/templates 中。

$ ls -m /usr/share/lxc/templates/
lxc-alpine, lxc-altlinux, lxc-archlinux, lxc-busybox, lxc-centos, lxc-cirros, lxc-debian, lxc-download, lxc-fedora, lxc-gentoo, lxc-openmandriva, lxc-opensuse, lxc-oracle, lxc-plamo, lxc-slackware, lxc-sparclinux, lxc-sshd, lxc-ubuntu, lxc-ubuntu-cloud

选择您喜欢的模板,然后创建容器。此示例使用 Slackware。

$ sudo lxc-create --name slackware --template slackware

观看模板的执行过程几乎与从头开始构建模板一样具有教育意义;它非常详细,您可以看到 lxc-create 将容器的“根”设置为 /var/lib/lxc/slackware/rootfs,并且正在将多个软件包下载并安装到该目录中。

通读模板文件可以让您更好地了解其中涉及的内容:LXC 设置了最小的设备树、常用 spool 文件、文件系统表 (fstab)、init 文件等等。它还阻止了一些在容器中没有意义的服务(例如用于硬件检测的 udev)启动。由于模板涵盖了广泛的典型 Linux 配置,如果您打算设计自己的模板,明智的做法是将您的工作基于最接近您想要设置的模板;否则,您肯定会犯遗漏错误(如果不是其他错误),而 LXC 项目已经遇到并解决了这些错误。

安装了最小的操作系统环境后,您可以启动您的容器。

$ sudo lxc-start --name slackware \
--rcfile ~/mycontainer.conf

您已启动容器,但尚未连接到它。(与之前的基本示例不同,这次您不仅是运行 shell,而是运行容器化的操作系统。)通过名称连接到它。

$ sudo lxc-attach --name slackware
#

检查您的环境的 IP 地址是否与您的配置文件中的地址匹配。

# /usr/sbin/ip addr show | grep eth
34: eth0@if35: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 [...] 1000
link/ether 4a:49:43:49:79:bd brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.168.168.167/24 brd 192.168.168.255 scope global eth0

退出容器,并将其关闭。

# exit
$ sudo lxc-stop slackware

使用 LXC 运行真实世界的容器

在现实生活中,LXC 可以轻松创建和运行安全可靠的容器。自 2008 年 LXC 推出以来,容器已经取得了长足的进步,因此请充分利用其开发人员的专业知识。

虽然 linuxcontainers.org 上的 LXC 说明使该过程变得简单,但手动方面的这次巡览应该有助于您了解幕后发生的事情。

标签
Seth Kenlon
Seth Kenlon 是一位 UNIX 极客、自由文化倡导者、独立多媒体艺术家和 D&D 爱好者。他曾在电影和计算机行业工作,而且经常同时从事这两个行业。

1 条评论

很好的信息。感谢分享。

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 许可。
© . All rights reserved.